#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "AS608.h"
#include "JQ8900.h"
#include "driver/gpio.h"
#include <string.h>
static QueueHandle_t uaert_queue;
uart_event_t uart_ev;
uint8_t uart_buffer[1024];
const uint16_t Head = 0x01EF;
const uint32_t AS608_Addr = 0xFFFFFFFF;


void User_Uart2_Init(int baud_rate)
{
    uart_config_t uart_structure = {
        .baud_rate = baud_rate,
        .data_bits = UART_DATA_8_BITS,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .parity = UART_PARITY_DISABLE,
        .source_clk = UART_SCLK_DEFAULT,
        .stop_bits = UART_STOP_BITS_1,
    };
    uart_param_config(USER_UART,&uart_structure);
    uart_set_pin(USER_UART,USER_TX,USER_RX,UART_PIN_NO_CHANGE,UART_PIN_NO_CHANGE);
    uart_driver_install(USER_UART,1024,1024,20,&uaert_queue,0);
}

void Touch_PinSet()
{
    gpio_config_t touch_sturcture = {
        .intr_type = GPIO_INTR_DISABLE,
        .mode = GPIO_MODE_INPUT,
        .pin_bit_mask = (1<<TOUCH_PIN), //设置13号脚为感应脚
        .pull_down_en = GPIO_PULLDOWN_ENABLE,
    };
    gpio_config(&touch_sturcture);
}

void Uart_SendHead()
{
    uart_write_bytes(USER_UART,&Head,sizeof(Head));
}

void Uart_SendAddr()
{
    uart_write_bytes(USER_UART,&AS608_Addr,sizeof(AS608_Addr));
}

void Uart_Sendflag(uint8_t flag)
{
    uart_write_bytes(USER_UART,&flag,sizeof(flag));
}

void Uart_Sendlenth(uint16_t lenth)
{
    uart_write_bytes(USER_UART,(uint8_t *)(&lenth) + 1,1);
    uart_write_bytes(USER_UART,(uint8_t *)(&lenth),1);
}

void Uart_Sendcmd(uint8_t cmd)
{
    uart_write_bytes(USER_UART,&cmd,sizeof(cmd));
}

void Uart_Sendcheck(uint16_t check)
{
    uart_write_bytes(USER_UART,(uint8_t *)(&check) + 1,1);
    uart_write_bytes(USER_UART,(uint8_t *)(&check),1);
}

//判断接收的数组有没有应答�?
//waittime为等待中�?接收数据的时间（单位1ms�?
//返回值：数据包�?�地址
uint8_t * MY_Judge(int waittime)
{
    char * data;
    uint8_t str[8] = {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x07,'\0'};
    if(pdTRUE == xQueueReceive(uaert_queue,&uart_ev,pdMS_TO_TICKS(waittime)))
    {
        if(uart_ev.type == UART_DATA)
        {
            uart_read_bytes(USER_UART,uart_buffer,uart_ev.size,pdTICKS_TO_MS(50));
            data = strstr((char *)uart_buffer,(char *)str);
            if(data)
            {
                return (uint8_t *)data;
            }
        }
    }
    return 0;
}


//录入图像 AS608_GetImage
//功能:探测手指，探测到后录入指纹图像存于ImageBuffer�? 
//模块返回�?认字

uint8_t AS608_GetImage()
{
    uint16_t check;
    uint8_t ensure;
    uint8_t * data;
    //uint8_t i = 0;
    Uart_SendHead();
    Uart_SendAddr();
    Uart_Sendflag(0x01);
    Uart_Sendlenth(0x03);
    Uart_Sendcmd(0x01);
    check = 0x01 + 0x03 + 0x01;
    Uart_Sendcheck(check);
    data = MY_Judge(2000);
    // for(i = 0;i < 12;i++)
    // {
    //     ESP_LOGI("uart","%d",data[i]);
    // }
    if(data)
        ensure = data[9];
    else
        ensure = 0xff;
    
    return ensure;
}


//生成特征 
//功能:将ImageBuffer�?的原始图像生成指纹特征文件存于CharBuffer1或CharBuffer2			 
//参数:BufferID --> charBuffer1:0x01	charBuffer1:0x02												
//模块返回�?认字
uint8_t AS608_GenChar(uint8_t BufferID)
{
    uint16_t check;
    uint8_t ensure;
    uint8_t * data;
    //uint8_t i = 0;
    Uart_SendHead();
    Uart_SendAddr();
    Uart_Sendflag(0x01);
    Uart_Sendlenth(0x04);
    Uart_Sendcmd(0x02);
    uart_write_bytes(USER_UART,&BufferID,sizeof(BufferID));
    check = 0x01 + 0x04 + 0x02 + BufferID;
    Uart_Sendcheck(check);
    data = MY_Judge(2000);
    /* for(i = 0;i < 12;i++)
    {
        ESP_LOGI("uart","%x",data[i]);
    } */
    if(data)
        ensure = data[9];
    else
        ensure = 0xff;
    
    return ensure;
}

//精确比�?�两枚指纹特�? 
//功能:精确比�?�CharBuffer1 与CharBuffer2 �?的特征文�? 
//模块返回�?认字
uint8_t AS608_Match()
{
    uint16_t check;
    uint8_t ensure;
    uint8_t * data;
    //uint8_t i = 0;
    Uart_SendHead();
    Uart_SendAddr();
    Uart_Sendflag(0x01);
    Uart_Sendlenth(0x03);
    Uart_Sendcmd(0x03);
    check = 0x01 + 0x03 + 0x03;
    Uart_Sendcheck(check);
    data = MY_Judge(2000);
    /* for(i = 0;i < 14;i++)
    {
        ESP_LOGI("uart","%x",data[i]);
    } */
    if(data)
        ensure = data[9];
    else
        ensure = 0xff;
    
    return ensure;
}

//合并特征（生成模板）
//功能:将CharBuffer1与CharBuffer2�?的特征文件合并生�? 模板,结果存于CharBuffer1与CharBuffer2	
//说明:  模块返回�?认字
uint8_t AS608_RegModel()
{
    uint16_t check;
    uint8_t ensure;
    uint8_t * data;
    //uint8_t i = 0;
    Uart_SendHead();
    Uart_SendAddr();
    Uart_Sendflag(0x01);
    Uart_Sendlenth(0x03);
    Uart_Sendcmd(0x05);
    check = 0x01 + 0x03 + 0x05;
    Uart_Sendcheck(check);
    data = MY_Judge(2000);
    if(data)
        ensure = data[9];
    else
        ensure = 0xff;

    return ensure;
}


//储存模板 
//功能:�? CharBuffer1 �? CharBuffer2 �?的模板文件存�? PageID 号flash数据库位�?�?			
//参数:  BufferID @ref charBuffer1:0x01	charBuffer1:0x02
//       PageID（指纹库位置号）
//说明:  模块返回�?认字
uint8_t AS608_StoreChar(uint8_t BufferID,uint16_t PageID)
{
    uint16_t check;
    uint8_t ensure;
    uint8_t * data;
    //uint8_t i = 0;
    Uart_SendHead();
    Uart_SendAddr();
    Uart_Sendflag(0x01);
    Uart_Sendlenth(0x06);
    Uart_Sendcmd(0x06);
    uart_write_bytes(USER_UART,&BufferID,sizeof(BufferID));
    uart_write_bytes(USER_UART,(uint8_t *)(&PageID) + 1,1);
    uart_write_bytes(USER_UART,(uint8_t *)(&PageID),1);
    check = 0x01 + 0x06 + 0x06 + BufferID + (PageID>>8) + (uint8_t)PageID;
    Uart_Sendcheck(check);
    data = MY_Judge(2000);
    /* for(i = 0;i < 12;i++)
    {
        ESP_LOGI("uart","%x",data[i]);
    } */
    if(data)
        ensure = data[9];
    else
        ensure = 0xff;

    return ensure;
}

//搜索指纹 
//功能:�?CharBuffer1或CharBuffer2�?的特征文件搜索整�?或部分指纹库.若搜索到，则返回页码�?			
//参数:  BufferID @ref CharBuffer1	CharBuffer2
//说明:  模块返回�?认字，页码（相配指纹模板�?
uint8_t AS608_Search(uint8_t BufferID,uint16_t StartPage,uint16_t PageNum,SearchResult_t *result)
{
    uint16_t check;
    uint8_t ensure;
    uint8_t * data;
    //uint8_t i = 0;
    Uart_SendHead();
    Uart_SendAddr();
    Uart_Sendflag(0x01);
    Uart_Sendlenth(0x08);
    Uart_Sendcmd(0x04);
    uart_write_bytes(USER_UART,&BufferID,sizeof(BufferID));
    uart_write_bytes(USER_UART,(uint8_t *)(&StartPage) + 1,1);
    uart_write_bytes(USER_UART,(uint8_t *)(&StartPage),1);
    uart_write_bytes(USER_UART,(uint8_t *)(&PageNum) + 1,1);
    uart_write_bytes(USER_UART,(uint8_t *)(&PageNum),1);
    check = 0x01 + 0x08 + 0x04 + BufferID + (StartPage>>8) + (uint8_t)StartPage + (PageNum>>8) + (uint8_t)PageNum;
    Uart_Sendcheck(check);
    data = MY_Judge(2000);
    if(data)
    {
        ensure = data[9];
        result->PageID = (data[10] << 8) + data[11];
        result->MatchScore = (data[12] << 8) + data[13];
    }
    else
        ensure = 0xff;

    return ensure;
}

//删除模板 PS_DeletChar
//功能:  删除flash数据库中指定ID号开始的N�?指纹模板
//参数:  PageID(指纹库模板号)，N删除的模板个数�?
//说明:  模块返回�?认字
uint8_t AS608_DeleteChar(uint16_t PageID,uint16_t num)
{
    uint16_t check;
    uint8_t ensure;
    uint8_t * data;
    //uint8_t i = 0;
    Uart_SendHead();
    Uart_SendAddr();
    Uart_Sendflag(0x01);
    Uart_Sendlenth(0x07);
    Uart_Sendcmd(0x0c);
    uart_write_bytes(USER_UART,(uint8_t *)(&PageID) + 1,1);
    uart_write_bytes(USER_UART,(uint8_t *)(&PageID),1);
    uart_write_bytes(USER_UART,(uint8_t *)(&num) + 1,1);
    uart_write_bytes(USER_UART,(uint8_t *)(&num),1);
    check = 0x01 + 0x07 + 0x0C + (PageID>>8) + (uint8_t)PageID + (num>>8) + (uint8_t)num;
    Uart_Sendcheck(check);
    data = MY_Judge(2000);
    if(data)
        ensure = data[9];
    else
        ensure = 0xff;

    return ensure;
}

//判断�?否有指纹按下，�?�果有则返回1，没有返�?0
uint8_t Judge_FingerPress()
{
    uint8_t level;
    level = gpio_get_level(TOUCH_PIN);
    return level;
}

//指纹录入
uint8_t Fingerprint_Register(uint16_t ID)
{
    uint8_t ensure = 0;
    uint8_t waittime = 10;
    uint8_t process = 0;
    ESP_LOGI("uart","=-------Fingerprint Start=-----------");
    Specify_Repertoire(0x02);
    vTaskDelay(pdMS_TO_TICKS(2000));
    while(1)
    {
        if(process == 0) //�?一次录入指�?
        {
            ESP_LOGI("uart","Please press your finger ----->");
            Specify_Repertoire(0x01);
            vTaskDelay(pdMS_TO_TICKS(2000));
            while(--waittime)
            {
                if(Judge_FingerPress())
                {
                    ESP_LOGI("uart","fingerprint getting......");
                    Specify_Repertoire(0x03);
                    vTaskDelay(pdMS_TO_TICKS(2000));
                    break;
                }
                else
                    ESP_LOGI("uart","Please press your finger ----->");
                ESP_LOGI("uart","%d",waittime);
                vTaskDelay(pdMS_TO_TICKS(1000));  
            }
            if(waittime == 0)
            {
                ESP_LOGI("uart","No finger press!!!");
                Specify_Repertoire(0x04);
                vTaskDelay(pdMS_TO_TICKS(2000));
                break;
            }
            else
            {
                ensure = AS608_GetImage();
                if(ensure == 0x00)
                {
                    ensure = AS608_GenChar(0x01);
                    if(ensure == 0x00)
                    {
                        process++;
                        ESP_LOGI("uart","fingerprint get success");
                        Specify_Repertoire(0x05);
                        vTaskDelay(pdMS_TO_TICKS(2000));
                    }
                    else
                    {
                        ESP_LOGI("uart","fingerprint genarate char failed");
                        Specify_Repertoire(0x06);
                        vTaskDelay(pdMS_TO_TICKS(2000));
                        process = 0;
                    }
                }
                else
                {
                    ESP_LOGI("uart","fingerprint get failed");
                    Specify_Repertoire(0x06);
                    vTaskDelay(pdMS_TO_TICKS(2000));
                    process = 0;
                }
            }
        }//�?一次录入指�?

        else if(process == 1) //�?二�?�录入指�?
        {
            waittime = 10;
            ESP_LOGI("uart","please press your finger again------>");
            Specify_Repertoire(0x07);
            vTaskDelay(pdMS_TO_TICKS(4000));
            while(--waittime)
            {
                if(Judge_FingerPress())
                {
                    ESP_LOGI("uart","fingerprint getting......");
                    Specify_Repertoire(0x03);
                    vTaskDelay(pdMS_TO_TICKS(2000));
                    break;
                }
                else
                    ESP_LOGI("uart","Please press your finger again----->");
                ESP_LOGI("uart","%d",waittime);
                vTaskDelay(pdMS_TO_TICKS(1000));  
            }
            if(waittime == 0)
            {
                ESP_LOGI("uart","No finger press!!!");
                Specify_Repertoire(0x04);
                vTaskDelay(pdMS_TO_TICKS(2000));
                return FAIL;
            }
            else
            {
                ensure = AS608_GetImage();
                if(ensure == 0x00)
                {
                    ensure = AS608_GenChar(0x02);
                    if(ensure == 0x00)
                        process++;
                    else
                    {
                        ESP_LOGI("uart","fingerprint genarate char failed");
                        Specify_Repertoire(0x06);
                        vTaskDelay(pdMS_TO_TICKS(2000));
                        process = 0;
                    }
                }
                else
                {
                    ESP_LOGI("uart","fingerprint get failed");
                    Specify_Repertoire(0x06);
                    vTaskDelay(pdMS_TO_TICKS(2000));
                    process = 0;
                }
            }
        }//�?二�?�录入指�?

        if(process == 2)//精准比�?�两次指�?
        {
            ESP_LOGI("uart","------------------");
            Specify_Repertoire(0x08);
            vTaskDelay(pdMS_TO_TICKS(3000));
            ensure = AS608_Match();
            if(ensure == 0x00)
            {
                process++;
            }   
            else
            {
                ESP_LOGI("uart","The fingerprints matched FAIL!!!");
                ESP_LOGI("uart","Please regist again! <--------");
                Specify_Repertoire(0x09);
                vTaskDelay(pdMS_TO_TICKS(5000));
                process = 0;
            }
        }//精准比�?�两次指�?

        if(process == 3)//合成特征并存储模�?
        {
            ensure = AS608_RegModel();
            if(ensure == 0x00)
            {
                ensure = AS608_StoreChar(0x01,ID);
                if(ensure == 0x00)
                {
                    ESP_LOGI("uart","指纹录入成功�?");
                    Specify_Repertoire(0x0A);
                    vTaskDelay(pdMS_TO_TICKS(2000));
                    return SUCCESS;
                }
                else
                {
                    ESP_LOGI("uart","指纹录失败功�?");
                    Specify_Repertoire(0x0B);
                    vTaskDelay(pdMS_TO_TICKS(2000));
                    process = 0;
                }
            }
            else
            {
                ESP_LOGI("uart","指纹录入失败�?");
                ESP_LOGI("uart","Please regist again! <--------");
                Specify_Repertoire(0x0B);
                vTaskDelay(pdMS_TO_TICKS(2000));
                process = 0;
            }
            
        }//合成特征并存储模�?
    }

    return 0;
}

uint8_t Fingerprint_Search(SearchResult_t * SearchResult)
{
    uint8_t ensure;
    uint8_t waittime = 10;
    ESP_LOGI("uart","签到开始，请按手指---------->");
    Specify_Repertoire(0x0C);
    vTaskDelay(pdMS_TO_TICKS(3000));
    while(--waittime)
    {
        if(Judge_FingerPress())
        {
            ESP_LOGI("uart","fingerprint getting......");
            Specify_Repertoire(0x02);
            vTaskDelay(pdMS_TO_TICKS(2000));
            break;
        }
        else
            ESP_LOGI("uart","Please press your finger ----->");
        ESP_LOGI("uart","%d",waittime);
        vTaskDelay(pdMS_TO_TICKS(1000));  
    }
    if(waittime == 0)
    {
        ESP_LOGI("uart","No finger press!!!");
        Specify_Repertoire(0x04);
        vTaskDelay(pdMS_TO_TICKS(3000));
        return FAIL;
    }
    else
    {
        ensure = AS608_GetImage();
        if(ensure == 0x00)
        {
            ESP_LOGI("uart","比�?�手指中.......");
            Specify_Repertoire(0x08);
            vTaskDelay(pdMS_TO_TICKS(2000));
            ensure = AS608_GenChar(0x01);
            if(ensure == 0x00)
            {
                ensure = AS608_Search(0x01,0,300,SearchResult);
                if(ensure == 0x00)
                {
                    ESP_LOGI("uart","搜索成功，�?�到成功！！�?");
                    ESP_LOGI("uart","指纹所在ID:%d",SearchResult->PageID);
                    Specify_Repertoire(0x0D);
                    vTaskDelay(pdMS_TO_TICKS(2000));
                    return SUCCESS;
                }
                else
                {
                    ESP_LOGI("uart","搜索失败！！�?");
                    Specify_Repertoire(0x0E);
                    vTaskDelay(pdMS_TO_TICKS(2000));
                    return FAIL;
                }
            }
        }
    }
    return 0;
}

